var _ = require('lodash'),
    Q = require('q'),
    mongoose = require('mongoose'),
    PublicEnum = require('../../../Base/server/controllers/Enum'),
    Transaction = require('../../../Base/server/controllers/Transaction'),
    entityCollection = require('../../../Base/server/controllers/EntityCollection'),
    barcodeMasterController = require('../../../Barcode/server/controllers/BarcodeMaster.server.controller'),
    kanbanDemandController = require('../../../ProduceWork/server/controllers/KanbanDemand.server.controller'),
    rcvRecordController = require('../../../ProduceWork/server/controllers/RcvRecord.server.controller'),
    connectAreaController = require('../../../CBO/server/controllers/WareHouse.server.controller'),
    terminalController = require('../../../CBO/server/controllers/Terminal.server.controller'),
    DeliveryRecordController = require('../../../ProduceWork/server/controllers/DeliveryRecord.server.controller'),
    ContainerController = require('../../../CBO/server/controllers/Container.server.controller');

exports.createKanban = function(req, res) {
    var parameter = req.body.Parameter,
        barcode = parameter.Barcode,
        userId = req.user._id;

    checkKanbanExist(barcode).then(function(result) {
            return Q.when(result.exist ? result.MO : createKanbanRecords(result.MO, userId));
        }).then(function(results) {
            res.json({
                Data: true,
                Error: null
            });
        }).catch(function(err) {
            res.json({
                Data: null,
                Error: err
            });
        })
        .done();
};

function checkKanbanExist(barcode) {
    var deferred = Q.defer();

    barcodeMasterController.findBarcodeMaster(barcode, function(err, barcodeMaster) {
        if (err) {
            deferred.reject(err);
            return;
        }
        if (!barcodeMaster || barcodeMaster.BarcodeType != 0) {
            var newErr = new Error();
            newErr.leval = 9;
            newErr.title = '查询物料错误';
            newErr.message = '无法识别的芯片，请重新扫描！';
            deferred.reject(newErr);
            return;
        }
        kanbanDemandController.findOneByMoId(barcodeMaster.MO, function(err, demands) {
            if (err) {
                deferred.reject(err);
                return;
            }
            deferred.resolve({
                exist: demands ? true : false,
                MO: barcodeMaster.MO
            });
        });
    });

    return deferred.promise;
}

function createKanbanRecords(Mo, userId) {
    var deferred = Q.defer();

    connectAreaController.distinctId(function(err, areaIds) {
        if (err) {
            deferred.reject(err);
            return;
        }
        var kanbanDemandRecords = [];
        _.forEach(areaIds, function(areaId) {
            kanbanDemandRecords.push({
                RowStatus: PublicEnum.RowStatus.Insert,
                CreatedBy: userId,
                MO: Mo,
                ConnectArea: areaId
            });
        });
        Transaction.BatchSaveByTran([
                { EntityName: 'KanbanDemand', Records: kanbanDemandRecords }
            ],
            function(err, result) {
                if (err) {
                    deferred.reject(err);
                    return;
                }
                deferred.resolve(result);
            }
        );
    });

    return deferred.promise;
}

//通过终端获取交接区
exports.queryConnectAreaByTerminal = function(req, res) {
    var parameter = req.body.Parameter,
        uniqueID = parameter.uniqueID,
        isUp = true;
    if (parameter.isUp) {
        isUp = parameter.isUp;
    }
    terminalController.findByUniqueID(uniqueID, function(err, record) {
        if (err) {
            res.json({
                Data: null,
                Error: err
            });
            return;
        }
        if (record._id) {
            var entity = entityCollection.getEntity("StationTerminal");
            entity.findOne({ Terminal: record._id }, [{
                    path: 'WorkLocation',
                    select: 'Department'
                }],
                function(err, result) {
                    if (err) {
                        res.json({
                            Data: null,
                            Error: err
                        });
                    } else {
                        var queryCondition;
                        if (isUp) {
                            queryCondition = { UpDepartment: result.WorkLocation.Department };
                        } else {
                            queryCondition = { DownDepartment: record.WorkLocation.Department };
                        }
                        //通过用户部门获取交界区
                        connectAreaController.getConnectAreaByDepartment(queryCondition, function(err, connectAreaResult) {
                            if (err) {
                                res.json({
                                    Data: null,
                                    Error: err
                                });
                            } else {
                                res.json({
                                    Data: connectAreaResult,
                                    Error: null
                                });
                            }
                        });
                    }
                });
        } else {
            res.json({
                Data: null,
                Error: "通过终端UUID未查询到相关设备。"
            });
        }
    });
};

//获取上游看板需求
exports.GetUpStreamKanban = function(req, res) {
    var parameter = req.body.Parameter,
        userId = parameter.userId;
    getConnectArea(userId, true).then(function(connectArea) {
        if (!connectArea) {
            res.json({
                Data: null,
                Error: "该用户下没有对应的交接区，请添加相应的交接区信息。"
            });
            return;
        }
        Q.all([
            getRvRecordsByConnectArea(connectArea._id),
            getKanbanDemand({
                ConnectArea: connectArea._id,
                $where: "this.TotalDemandQty - this.TotalStockQty > 0"
            })
        ]).spread(function() {
            if (arguments.length < 2) {
                res.json({
                    Data: null,
                    Error: "通过交接区ID未查到入库记录或者没有满足的看板需求记录."
                });
                return;
            }
            var rvRecords = arguments[0],
                demands = arguments[1],
                kanban = [];
            _.forEach(rvRecords, function(rvRecord) {
                _.forEach(demands, function(demand) {
                    if (rvRecord._id.toString() == demand.MO.toString()) {
                        kanban.push({
                            Priority: demand.Priority == undefined ? 0 : demand.Priority,
                            NOLotNumber: rvRecord.value.barcode.MOLotNumber == undefined ? '' : rvRecord.value.barcode.MOLotNumber,
                            ItemMasterCode: rvRecord.value.barcode.ItemMasterCode == undefined ? '' : rvRecord.value.barcode.ItemMasterCode,
                            ItemMasterName: rvRecord.value.barcode.ItemMasterName == undefined ? '' : rvRecord.value.barcode.ItemMasterName,
                            TotalDemandQty: demand.TotalDemandQty == undefined ? 0 : demand.TotalDemandQty,
                            TotalNeedQty: (demand.TotalDemandQty - demand.TotalStockQty) == undefined ? 0 : (demand.TotalDemandQty - demand.TotalStockQty),
                            RcvQty: rvRecord.value.RcvQty == undefined ? 0 : rvRecord.value.RcvQty,
                            TotalStockQty: demand.TotalStockQty == undefined ? 0 : demand.TotalStockQty,
                            TotalReceiveQty: demand.TotalReceiveQty == undefined ? 0 : demand.TotalReceiveQty
                        });
                    }
                });
            });
            res.json({
                Data: kanban,
                Error: null
            });
        });
    });

};

//获取下游看板需求
exports.GetDownStreamKanban = function(req, res) {
    var parameter = req.body.Parameter,
        userId = parameter.userId;
    //入库记录(批次(工单)-库存)
    getConnectArea(userId, false).then(function(connectArea) {
        if (!connectArea) {
            res.json({
                Data: null,
                Error: "该用户下没有对应的交接区，请添加相应的交接区信息。"
            });
            return;
        }
        Q.all([
            getRvRecordsByConnectArea(connectArea._id),
            getKanbanDemand({
                ConnectArea: connectArea._id,
                $where: "this.TotalDemandQty - this.TotalReceiveQty > 0"
            })
        ]).spread(function() {
            if (arguments.length < 2) {
                res.json({
                    Data: null,
                    Error: "通过交接区ID未查到入库记录或者没有满足的看板需求记录."
                });
                return;
            }
            var rvRecords = arguments[0],
                demands = arguments[1],
                kanban = [];
            _.forEach(rvRecords, function(rvRecord) {
                _.forEach(demands, function(demand) {
                    if (rvRecord._id.toString() == demand.MO.toString()) {
                        kanban.push({
                            Priority: demand.Priority == undefined ? 0 : demand.Priority,
                            NOLotNumber: rvRecord.value.barcode.MOLotNumber == undefined ? '' : rvRecord.value.barcode.MOLotNumber,
                            ItemMasterCode: rvRecord.value.barcode.ItemMasterCode == undefined ? '' : rvRecord.value.barcode.ItemMasterCode,
                            ItemMasterName: rvRecord.value.barcode.ItemMasterName == undefined ? '' : rvRecord.value.barcode.ItemMasterName,
                            RcvQty: rvRecord.value.RcvQty == undefined ? 0 : rvRecord.value.RcvQty,
                            TotalReceiveQty: demand.TotalReceiveQty == undefined ? 0 : demand.TotalReceiveQty,
                            NeedDeliveryQty: (demand.TotalDemandQty - demand.TotalReceiveQty) == undefined ? 0 : (demand.TotalDemandQty - demand.TotalReceiveQty)
                        });
                    }
                });
            });
            res.json({
                Data: kanban,
                Error: null
            });
        }, function(err) {
            res.json({
                Data: null,
                Error: err
            });
        });
    });
};

//获取看板信息
exports.getKanbanDemandInfo = function(req, res) {
    var parameter = req.body.Parameter,
        workId = parameter.workId,
        workFlag = parameter.workFlag; //workFlag==true 代表查询条件是目的作业，false代表是转入作业
    var queryCondition;
    if (workFlag) {
        queryCondition = { TargetWork: workId };
    } else {
        queryCondition = { InputWork: workId };
    }
    connectAreaController.getWareHouseInfo(queryCondition, function(err, wareHouseInfo) {
        if (err) {
            res.json({
                Data: null,
                Error: err
            });
        } else {
            if (wareHouseInfo) {
                kanbanDemandController.findRecordsByCondition({ WareHouse: wareHouseInfo._id }, function(err, records) {
                    if (err) {
                        res.json({
                            Data: null,
                            Error: err
                        });
                    } else {
                        res.json({
                            Data: records,
                            Error: null
                        });
                    }
                });
            } else {
                var newErr = new Error();
                newErr.leval = 9;
                newErr.title = '查询错误';
                newErr.message = '没有查询到相应的待转区';
                res.json({
                    Data: null,
                    Error: err
                });
            }
        }
    });
};

//获取容器
exports.getContainer = function(req, res) {
    var parameter = req.body.Parameter,
        entityId = parameter.entityId;
    ContainerController.getContainerById(entityId, function(err, record) {
        if (err) {
            res.json({
                Data: null,
                Error: err
            });
        } else {
            res.json({
                Data: record,
                Error: null
            });
        }
    });
};

//交接区检货UdpatePIckUpQty,确认服务
exports.PIckUp = function(req, res) {
    var parameter = req.body.Parameter,
        userId = parameter.userId,
        validBarcodeList = parameter.validBarcodeList,
        containerId = parameter.containerId,
        moAndNum = parameter.moAndNum,
        workId = parameter.workId,
        workFlag = parameter.workFlag,
        MOList = [];
    var queryCondition;
    if (workFlag) {
        queryCondition = { TargetWork: workId };
    } else {
        queryCondition = { InputWork: workId };
    }
    _.forEach(moAndNum, function(value, key) {
        MOList.push(key);
    });
    connectAreaController.getWareHouseInfo(queryCondition, function(err, wareHouseInfo) {
        if (err) {
            res.json({
                Data: null,
                Error: err
            });
        } else {
            if (wareHouseInfo) {
                Q.all([
                    updateKanbanByCondition('pIck', {
                        WareHouse: wareHouseInfo._id,
                        MO: { $in: MOList }
                    }, moAndNum),
                    updateRcvRecord('update', validBarcodeList, containerId)

                ]).spread(function() {});
                if (arguments.length < 2) {
                    var newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '查询错误';
                    newErr.message = '看板或者入库记录查询失败';
                    res.json({
                        Data: null,
                        Error: err
                    });
                    return;
                }
                var kanbanArray = arguments[0],
                    rcvRecords = arguments[1],
                    deliveryRecord = [];
                deliveryRecord.push({
                    WareHouse: wareHouseInfo._id,
                    Container: containerId,
                    Status: 0,
                    Qty: validBarcodeList.length,
                    ReadyTime: new Date(),
                    StockPerson: userId,
                    RowStatus: PublicEnum.RowStatus.Insert
                });

                Transaction.BatchSaveByTran(
                    [
                        { EntityName: 'KanbanDemand', Records: kanbanArray },
                        { EntityName: 'RcvRecord', Records: rcvRecords },
                        { EntityName: 'DeliveryRecord', Records: deliveryRecord }
                    ],
                    function(err, result) {
                        if (err) {
                            res.json({
                                Data: null,
                                Error: err
                            });
                        } else {
                            res.json({
                                Data: result,
                                Error: null
                            });
                        }
                    }
                );
            }
        }
    });
};

//交接区收货UpdateArrivedQty,确认服务
exports.Arrived = function(req, res) {
    userId = parameter.userId,
        validBarcodeList = parameter.validBarcodeList,
        inValidBarcodeList = parameter.inValidBarcodeList,
        containerId = parameter.containerId,
        moAndNum = parameter.moAndNum,
        workId = parameter.workId,
        workFlag = parameter.workFlag,
        MOList = [];
    var queryCondition;
    if (workFlag) {
        queryCondition = { TargetWork: workId };
    } else {
        queryCondition = { InputWork: workId };
    }
    _.forEach(moAndNum, function(value, key) {
        MOList.push(key);
    });
    connectAreaController.getWareHouseInfo(queryCondition, function(err, wareHouseInfo) {
        if (err) {
            res.json({
                Data: null,
                Error: err
            });
        } else {
            if (wareHouseInfo) {
                Q.all([
                    updateKanbanByCondition('pIck', {
                        WareHouse: wareHouseInfo._id,
                        MO: { $in: MOList }
                    }, moAndNum),
                    updateRcvRecord('del', validBarcodeList, containerId),
                    updateRcvRecord('update', inValidBarcodeList, ''),
                    updateDeliveryRecord(containerId)

                ]).spread(function() {});
                if (arguments.length < 4) {
                    var newErr = new Error();
                    newErr.leval = 9;
                    newErr.title = '查询错误';
                    newErr.message = '记录查询失败';
                    res.json({
                        Data: null,
                        Error: err
                    });
                    return;
                }
                var kanbanArray = arguments[0],
                    delRcvRecords = arguments[1],
                    updateRcvRecords = arguments[2],
                    deliveryRecord = arguments[3];

                    Transaction.BatchSaveByTran(
                        [
                            { EntityName: 'KanbanDemand', Records: kanbanArray },
                            { EntityName: 'RcvRecord', Records: delRcvRecords },
                            { EntityName: 'RcvRecord', Records: updateRcvRecords },
                            { EntityName: 'DeliveryRecord', Records: deliveryRecord }
                        ],
                        function(err, result) {
                            if (err) {
                                res.json({
                                    Data: null,
                                    Error: err
                                });
                            } else {
                                res.json({
                                    Data: result,
                                    Error: null
                                });
                            }
                        }
                    );
            }
        }
    });

};

//交接检查是获取球拍的检查状态、重复扫描的合规性
exports.getBarcodeMasterInfo = function(req, res) {
    var parameter = req.body.Parameter,
        Barcode = parameter.Barcode;
    var entityRcvRecord = entityCollection.getEntity("RcvRecord"),
        entityBarcodeMaster = entityCollection.getEntity("BarcodeMaster");
    //现根据芯片ID检查入库记录，做重复扫描的合规性检查
    entityRcvRecord.findOne({ Barcode: Barcode }, null, function(err, record) {
        if (err) {
            res.json({
                Data: null,
                Error: err
            });
            return;
        }
        if (!record) {
            res.json({
                Data: "此球拍没有做入库或这是重复扫描",
                Error: null
            });
            return;
        } else {
            //接收芯片对应的条码主档
            entityBarcodeMaster.findOne({ Barcode: Barcode }, null, function(err, record) {
                if (err) {
                    res.json({
                        Data: null,
                        Error: err
                    });
                    return;
                }
                res.json({
                    Data: record,
                    Error: null
                });
            });
        }
    });
};

//通过用户ID获取交接区信息,flag == true(上游)，flag == false(下游)
function getConnectArea(userId, flag) {
    var deferred = Q.defer();
    var userModel = mongoose.model('User');
    //通过用户ID获取部门
    userModel.findOne({ _id: userId }, { Department: 1 }).exec(function(err, record) {
        if (err) {
            deferred.reject(err);
        }

        if (!record) {
            deferred.reject("用户对应部门为空");
        }
        var queryCondition = {};
        if (flag) {
            queryCondition = { UpDepartment: record.Department };
        } else {
            queryCondition = { DownDepartment: record.Department };
        }
        //通过用户部门获取交界区
        var entity = entityCollection.getEntity("WareHouse");
        entity.findOne(queryCondition, null, function(err, result) {
            if (err) {
                deferred.reject(err);
            } else {
                deferred.resolve(result);
            }
        });
    });
    return deferred.promise;
}

//根据芯片ID(Barcode)，分组key,获取条码主档[key,value]
function queryByBarcodeAndGroupByMo(key, barcodeList) {
    var deferred = Q.defer();
    var entityBarcodeMaster = entityCollection.getEntity("BarcodeMaster");
    entityBarcodeMaster.aggregateCount(key, { Barcode: { $in: barcodeList } }, function(err, data) {
        if (err) {
            deferred.reject(err);
        }
        deferred.resolve(data);
    });
    return deferred.promise;
}

//根据交界区ID取得看板
function getKanbanDemand(condition) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("KanbanDemand");
    entity.find(condition, null, null, function(err, results) {
        if (err) {
            deferred.reject(err);
        } else {
            deferred.resolve(results);
        }
    });
    return deferred.promise;
}

//根据交接区ID获取入库记录
function getRvRecordsByConnectArea(connectAreaId) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("RcvRecord");

    var barcodeMap = function() {
        emit(this.BusinessDocID, { barcode: this.BarcodeMaster, RcvQty: this.RcvQty });
    };

    var reduce = function(key, values) {
        return { barcode: this.BarcodeMaster, RcvQty: Array.sum(values.RcvQty) }
    };

    var query = {
        //connectAreaId: connectAreaId,
        //Location: null
    };

    var option = {
        map: barcodeMap,
        reduce: reduce,
        query: query
    };

    entity.mapReduce(option, function(err, results) {
        var barcodeModel = mongoose.model('BarcodeMaster');
        barcodeModel.populate(results, { path: 'value.barcode' }, function(err, resultsBarcodes) {
            deferred.resolve(resultsBarcodes);
        });
    });

    return deferred.promise;
}

//根据芯片ID(Barcode)获取入库记录
function getRcvRecordsByBarcode(barcodeList) {
    var deferred = Q.defer();
    var entity = entityCollection.getEntity("RcvRecord");
    entity.find({ Barcode: { $in: [barcodeList] } }, null, null, function(err, records) {
        if (err) {
            deferred.reject(err);
        } else {
            deferred.resolve(records);
        }
    });
    return deferred.promise;
}

//获取看板更新数据
function updateKanbanByCondition(flg, condition, moAndNum) {
    var deferred = Q.defer();
    kanbanDemandController.findRecordsByCondition(condition, function(err, records) {
        if (err) {
            deferred.reject(err);
        } else {
            _.forEach(records, function(record) {
                if (moAndNum.hasOwnProperty(record.MO)) {
                    if (flg === 'pIck') {
                        record.TotalStockQty += moAndNum[record.MO];
                    } else {
                        record.TotalReceiveQty += moAndNum[record.MO];
                    }

                    record.RowStatus = PublicEnum.RowStatus.Modify;
                }
            });
            deferred.resolve(records);
        }
    });
    return deferred.promise;
}
//获取入库记录更新数据
function updateRcvRecord(flg, Barcodes, containerId) {
    var deferred = Q.defer();
    rcvRecordController.queryByCondition({
        Barcode: { $in: Barcodes }
    }, function(err, records) {
        if (err) {
            deferred.reject(err);
        } else {
            _.forEach(records, function(record) {
                if (flg === 'update') {
                    record.RowStatus = PublicEnum.RowStatus.Modify;
                } else if (flg === 'del') {
                    record.RowStatus = PublicEnum.RowStatus.Delete;
                } else {

                }
                record.Container = containerId;
            });
            deferred.resolve(records);
        }
    });
    return deferred.promise;
}

function updateDeliveryRecord(containerId) {
    var deferred = Q.defer();
    DeliveryRecordController.queryByCondition({ Container: containerId }, function(err, record) {
        if (err) {
            deferred.reject(err);
        } else {
            record.RowStatus = PublicEnum.RowStatus.Modify,
                record.Status = 2,
                record.Qty = validBarcodeList.length,
                record.ReadyTime = new Date()
            deferred.resolve(record);
        }
    });
    return deferred.promise;
}
